import utime
from micropython import const

class AHT20:
    AHTX0_I2CADDR_DEFAULT = const(0x38)  # 默认 I2C 地址
    AHTX0_CMD_INITIALIZE = const(0xBE)  # 初始化命令
    AHTX0_CMD_TRIGGER = const(0xAC)  # 触发读取命令
    AHTX0_CMD_SOFTRESET = const(0xBA)  # 软复位命令
    AHTX0_STATUS_BUSY = const(0x80)  # 忙状态标志
    AHTX0_STATUS_CALIBRATED = const(0x08)  # 校准状态标志

    def __init__(self, i2c, address=AHTX0_I2CADDR_DEFAULT):
        utime.sleep_ms(20)  # 延时 20ms 以唤醒传感器
        self._i2c = i2c
        self._address = address
        self._buf = bytearray(6)
        self.reset()
        if not self.initialize():
            raise RuntimeError("无法初始化传感器")
        self._temp = None
        self._humidity = None

    def reset(self):
        """执行软复位"""
        self._buf[0] = self.AHTX0_CMD_SOFTRESET
        self._i2c.writeto(self._address, self._buf[0:1])
        utime.sleep_ms(20)  # 延时 20ms 以唤醒

    def initialize(self):
        """初始化传感器，返回 True 表示成功，False 表示失败"""
        self._buf[0] = self.AHTX0_CMD_INITIALIZE
        self._buf[1] = 0x08
        self._buf[2] = 0x00
        self._i2c.writeto(self._address, self._buf[0:3])
        self._wait_for_idle()
        if not self.status & self.AHTX0_STATUS_CALIBRATED:
            return False
        return True

    @property
    def status(self):
        """读取传感器状态字"""
        self._read_to_buffer()
        return self._buf[0]

    @property
    def relative_humidity(self):
        """读取相对湿度（百分比）"""
        self._perform_measurement()
        self._humidity = (
            (self._buf[1] << 12) | (self._buf[2] << 4) | (self._buf[3] >> 4)
        )
        self._humidity = (self._humidity * 100) / 0x100000
        return self._humidity

    @property
    def temperature(self):
        """读取温度（摄氏度）"""
        self._perform_measurement()
        self._temp = ((self._buf[3] & 0xF) << 16) | (self._buf[4] << 8) | self._buf[5]
        self._temp = ((self._temp * 200.0) / 0x100000) - 50
        return self._temp

    def _read_to_buffer(self):
        """将传感器数据读取到缓冲区"""
        self._i2c.readfrom_into(self._address, self._buf)

    def _trigger_measurement(self):
        """触发传感器测量"""
        self._buf[0] = self.AHTX0_CMD_TRIGGER
        self._buf[1] = 0x33
        self._buf[2] = 0x00
        self._i2c.writeto(self._address, self._buf[0:3])

    def _wait_for_idle(self):
        """等待传感器空闲"""
        while self.status & self.AHTX0_STATUS_BUSY:
            utime.sleep_ms(5)

    def _perform_measurement(self):
        """触发测量并将结果写入缓冲区"""
        self._trigger_measurement()
        self._wait_for_idle()
        self._read_to_buffer()
